/*
 * XPathEvaluator.java
 *
 * Created on October 17, 2007, 12:42 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package anything;

import java.io.IOException;
import org.xml.sax.SAXException;
import javax.xml.parsers.*; // ใช้ในการเริ่มต้น เตรียมการสร้าง DOM/SAX
import org.w3c.dom.*; // ใช้ในการสร้าง DOM ขึ้นมาและ traverse DOM tree
import javax.xml.xpath.*; // ใช้ในการทำ xpath เริ่มมีใน java 5

public class XPathEvaluator {

  public static void main(String[] args) {
    try {
      // ใช้ DOM ในการอ่าน xml ขึ้นมา
      DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
      // ถ้า xml document นี้มี namespace ต้องบอกให้ parser รู้แต่แรกก่อน / แต่เอกสาร xml นี้ไม่มี namespace
      Document doc = docBuilder.parse("res/test/bookstore.xml");
      // จะต้องใช้เอกสาร xml ในตัวอย่างก่อนมาทดสอบ โดยให้ชื่อว่า bookstore.xml

      // เรียก xpath มาประมวลผล
      // ส่วนที่ใช้ XPath Interface นี้ จะต้องใช้ java 5
      XPath xpath = XPathFactory.newInstance().newXPath();
      NodeList result = (NodeList)xpath.evaluate("/books/book", doc, XPathConstants.NODESET);

      // ส่วนนี้ เป็นการพิมพ์ผลลัพธ์ออกมา โดยการพิมพ์ออกมาทีละผลลัพธ์
      // ไม่เกี่ยวข้องกับ xpath แล้ว
      for (int i=0; i<result.getLength(); ++i) {
        System.out.println("Result " + (i+1) + " :");
        printNode(result.item(i), "  ");
      }
    }
    catch (ParserConfigurationException e) {
      System.err.println("Cannot create a document builder.");
    }
    catch (IOException e) {
      System.err.println("Cannot read the file.");
    }
    catch (SAXException e) {
      System.err.println("Cannot parse the xml file.");
    }
    catch (XPathExpressionException e) {
      System.err.println("Cannot evaluate the xpath.");
    }
  }

  // ส่วนนี้ไม่เกี่ยวกับ xpath แต่เป็นเพียงการพิมพ์แต่ละ node ออกมา
  // ตามด้วยลูกๆ โดยการย่อหน้าอย่างเหมาะสม
  // ตัวอย่างนี้ จะพิมพ์ออกมาเฉพาะ element node กับ text node เท่านั้น
  // เป็นการเขียนแบบ recursive เพื่อให้ backtracking ได้สะดวก
  // เป็นการแสดงการใช้ DOM เพื่อ traverse ไปตาม node ต่างๆ ของ document tree
  public static void printNode(Node n, String indent) {
    NodeList children = null;
    int count, size;
    switch (n.getNodeType()) {
      case Node.ELEMENT_NODE :
        System.out.println(indent + "<" + n.getNodeName() + ">"); // tag เปิด
        if (n.hasChildNodes()) { // ถ้ามีลูกๆ
          children = n.getChildNodes();
          for (count=0; count<children.getLength(); ++count) {
            printNode(children.item(count), indent + "  ");  // พิมพ์ลูกๆ และย่อหน้าเพิ่มขึ้น
          }
        }
        System.out.println(indent + "</" + n.getNodeName() + ">"); // tag ปิด
        break;
      case Node.TEXT_NODE :
        if (!n.getNodeValue().matches("\\s+")) { // ถ้าเป็น text ว่างๆ เปล่าๆ ไม่ต้องพิมพ์
          System.out.println(indent + n.getNodeValue());
        }
        break;
    }
  }
}